package dyyx.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;
import org.apache.zookeeper.data.Stat;

import dyyx.dto.NodeData;
import dyyx.dto.ZkClient;

public abstract class ClientUtil {
	
	private static volatile ZkClient zkClient;
	
	
	private static final String MYPATH = "/dyyx";
	
	
	public static synchronized Map<String,String> getZkInfoForDubbo()throws Exception{
		if(zkClient==null){
			return null;
		}
		ZooKeeper zk = zkClient.zk;
		States states = zk.getState();

		Map<String,String> map = new LinkedHashMap<>();
		map.put("connectString", zkClient.connectString);
		map.put("states", states.toString());
		map.put("alive", states.isAlive()+"");

		return map;
	}
	
	public static synchronized ZkClient getZkClient()throws Exception{
		if(zkClient==null){
			throw new Exception("not connected"); 
		}
		return zkClient;
	}
	
	public static synchronized void connect(String connstr)throws Exception{
		if(zkClient!=null){
			
			if(zkClient.zk.getState().isConnected()) {
				return;
			}
			
			throw new Exception("can disconnect and reconnect,current client info,"+getClientInfo()); 
		}
		ZkClient client = new ZkClient(connstr);
		zkClient = client;			
	}
	
	
	public static synchronized void disconnect()throws Exception{
		if(zkClient==null){
			throw new Exception("not connected"); 
		}
		zkClient.zk.close();
		zkClient = null;
	}
	
	
	public static synchronized NodeData getData(String path)throws Exception{
		if(zkClient==null){
			throw new Exception("not connected"); 
		}
		Stat stat = new Stat();
		byte[] data = zkClient.zk.getData(path, false, stat);
		
		return new NodeData(path,data,stat);
	}
	
	public static synchronized List<NodeData> getChildData(String path)throws Exception{
		if(zkClient==null){
			throw new Exception("not connected"); 
		}
		List<String> list = zkClient.zk.getChildren(path, false);
		if(list==null || list.isEmpty()){
			return null;
		}
		List<NodeData> datalist = new ArrayList<NodeData>();
		NodeData data = null;
		for(String item:list){
			data = getData(buildFullPath(path,item));
			datalist.add(data);
		}
		
		return datalist;
	}
	
	
	public static String  buildFullPath(String parent,String child){
		if(parent.endsWith("/")){
			return parent+child;
		}
		return parent+"/"+child;
		
	}
	
	public static synchronized boolean isConnected()throws Exception{
		if(zkClient==null){
			return false; 
		}
		return zkClient.zk.getState().isConnected();	
	}

	
	public static synchronized Map<String,Object> getClientInfo()throws Exception{
		if(zkClient==null){
			throw new Exception("not connected"); 
		}
		
		Map<String,Object> map = new LinkedHashMap<>();
		map.put("createTime", zkClient.createTime);
		map.put("connectString", zkClient.connectString);
		map.put("sessionTimeout", zkClient.sessionTimeout);
		map.put("sessionId", zkClient.sessionId);
		ZooKeeper zk = zkClient.zk;
		States states = zk.getState();
		map.put("connected", states.isConnected());
		map.put("alive", states.isAlive());
		map.put("states", states.toString());
		// map.put("isConnected", states.isConnected());
		
		// ZooKeeper zk = ClientUtil.getZkClient().zk;
		// ClientCnxn cnxn
		
		Field f = ZooKeeper.class.getDeclaredField("cnxn");
		f.setAccessible(true);
		
		map.put("cnxn", f.get(zk).toString());

		

		
		return map;
	}
	
	
	public static synchronized boolean canModify(String path)throws Exception{
		if(path==null){
			return false;
		}
		// chroot  only /dyyx can modify
		if(getZkClient().connectString.endsWith(MYPATH)){
			return true;
		}
		if(path.startsWith(MYPATH)){
			return true;
		}
		
		return false;
	}
	

}
